﻿#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QSerialPortInfo>
#include <QDebug>
#include <QDateTime>
#include <QThread>
#include <QTimer>

#if defined(_MSC_VER) && (_MSC_VER >= 1600)
#pragma execution_character_set("utf-8")
#endif


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 查询所有串口设备
    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();

    QStringList serialPortNameList;
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        serialPortNameList << info.portName();
        qDebug()<<"serialPortName: "<<info.portName();
    }
    // 展示在下拉列表中
    ui->comboBox->addItems(serialPortNameList);
    ui->lineEdit->setText("115200");


    m_serialPort = new QSerialPort(this);
    connect(m_serialPort, &QSerialPort::readyRead, this, &MainWindow::handleReadyRead);
    connect(m_serialPort, &QSerialPort::errorOccurred, this, &MainWindow::handleError);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::writeMsg(QString str)
{
    QString strLog = QString("%1 [%2]  %3").arg(QDateTime::currentDateTime().toString("hh:mm:ss zzz")).arg(quintptr(QThread::currentThreadId())).arg(str);

    QTextCursor tc = ui->textBrowser->textCursor();
    tc.movePosition(QTextCursor::End);
    tc.insertText(strLog + "\n");
    ui->textBrowser->moveCursor(QTextCursor::End);
}

bool MainWindow::waiteForReadyRead(int msec)
{
    QEventLoop eventloop;
    QObject::connect(this, &MainWindow::serialDataReadFinished, &eventloop, &QEventLoop::quit);

    bool isTimeout = false;
    QTimer::singleShot(msec, &eventloop, [&](){
        eventloop.quit();
        isTimeout = true;
    });

    eventloop.exec(QEventLoop::AllEvents);
    return !isTimeout;
}

void MainWindow::on_connectButton_clicked()
{
    if(ui->connectButton->text() == "连接")
    {
        QString portName = ui->comboBox->currentText();
        int baudRate = ui->lineEdit->text().toInt();

        m_serialPort->setPortName(portName);
        if(!m_serialPort->open(QIODevice::ReadWrite))
        {
            writeMsg(QString("串口[%1]打开失败，%2").arg(portName).arg(m_serialPort->errorString()));
            return;
        }

        m_serialPort->setBaudRate(baudRate, QSerialPort::AllDirections);
        m_serialPort->setDataBits(QSerialPort::Data8);             // 数据位为8位
        m_serialPort->setFlowControl(QSerialPort::NoFlowControl);  // 无流控制
        m_serialPort->setParity(QSerialPort::NoParity);            // 无校验位
        m_serialPort->setStopBits(QSerialPort::OneStop);           // 一位停止位

        writeMsg("打开串口成功");
        ui->connectButton->setText("断开连接");
    }
    else
    {
        m_serialPort->close();
        writeMsg("断开串口成功");
        ui->connectButton->setText("连接");
    }

}

void MainWindow::handleReadyRead()
{
    m_recvData = m_serialPort->readAll();
    writeMsg("异步收到：" + QString::fromUtf8(m_recvData));

    emit serialDataReadFinished();  // 自定义的事件，为了配合通知异步等待完成
}

void MainWindow::handleError(QSerialPort::SerialPortError serialPortError)
{
    if (serialPortError == QSerialPort::ReadError)
    {
        QString error = QString("An I/O error occurred while reading "
                                        "the data from port %1, error: %2")
                            .arg(m_serialPort->portName())
                            .arg(m_serialPort->errorString());
        writeMsg(error);
    }
}

void MainWindow::on_sendMsgButton_clicked()
{
    QString sendData = ui->textEdit->toPlainText();
    writeMsg("发送：" + sendData);

    m_serialPort->write(sendData.toUtf8(), sendData.toUtf8().size());
}



void MainWindow::on_sendMsgButton_2_clicked()
{
    QString sendData = ui->textEdit->toPlainText();
    writeMsg("发送：" + sendData);

    m_serialPort->write(sendData.toUtf8(), sendData.toUtf8().size());
    if(!waiteForReadyRead(5000))    // 自定义的异步等待函数
    {
        writeMsg("等待回复超时");
    }
    else
    {
        writeMsg("同步收到: " + m_recvData);
    }
}
